package com.ziyue.socket.websocket;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.ziyue.socket.bean.SocketRequest;
import com.ziyue.socket.cache.RoomManage;
import com.ziyue.socket.bean.SocketResponse;
import com.ziyue.socket.enums.OptionEnum;
import com.ziyue.socket.enums.SocketStatusEnum;
import com.ziyue.socket.exception.ChannelNotExistException;
import com.ziyue.socket.exception.IllegalOperationMessageException;
import com.ziyue.socket.exception.UnFullWebsocketMessageException;
import com.ziyue.socket.bean.Member;
import com.ziyue.socket.service.OptionAbstract;
import com.ziyue.socket.util.ReflectUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * Created by wancheng on 2019/3/13.
 */
public class TextWebSocketFrameHandler  extends
        SimpleChannelInboundHandler<TextWebSocketFrame> {

    public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    private RoomManage roomManage = RoomManage.getInstance();

    @Override
    protected void channelRead0(ChannelHandlerContext ctx,
                                TextWebSocketFrame msg) throws Exception {
        Channel incoming = ctx.channel();
        String msgBody = msg.text();
        SocketRequest socketRequest = null;
        socketRequest = JSONObject.parseObject(msgBody,SocketRequest.class);
        if (socketRequest.getOption() == null){
            throw new UnFullWebsocketMessageException();
        }
        OptionAbstract option = ReflectUtil.getInstance(socketRequest.getOption().getOptionClass());
        option.send(incoming, msgBody);

    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        channels.add(incoming);
        System.out.println("Client:"+incoming.remoteAddress() +"加入");
        incoming.writeAndFlush(new TextWebSocketFrame("加入"));
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println("Client:"+incoming.remoteAddress() +"离开");
        OptionAbstract option = ReflectUtil.getInstance(OptionEnum.INACTIVE.getOptionClass());
        option.send(incoming, null);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println("Client:"+incoming.remoteAddress()+"在线");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println("Client:"+incoming.remoteAddress()+"掉线");
        OptionAbstract option = ReflectUtil.getInstance(OptionEnum.INACTIVE.getOptionClass());
        option.send(incoming, null);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        Channel incoming = ctx.channel();
        SocketResponse response = new SocketResponse();
        Member member = roomManage.getMember(incoming.id());
        response.setCode(SocketStatusEnum.SOCKET_ERROR);
        Exception e = new Exception(cause);
        if (e instanceof ChannelNotExistException ){
            response.setMsg("连接断开,请重新开启连接");
            incoming.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(response)));
        }else if(e instanceof IllegalOperationMessageException){
            response.setMsg("非法的操作");
            incoming.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(response)));
        }else if(e instanceof UnFullWebsocketMessageException){
            response.setMsg("消息信息不完整!");
            incoming.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(response)));
        }else if (e instanceof JSONException){
            response.setMsg("参数解析错误!");
            incoming.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(response)));
        }else{
            response.setMsg("内部异常,连接断开!");
            response.setCode(SocketStatusEnum.SOCKET_EXCEPTION);
            incoming.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(response)));
            ctx.close();
        }
        cause.printStackTrace();
    }

    /**
     * 握手事件
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            Channel incoming = ctx.channel();
            //incoming.writeAndFlush(new TextWebSocketFrame("web socket 握手成功。"));
            System.out.println("web socket 握手成功。");
            WebSocketServerProtocolHandler.HandshakeComplete handshakeComplete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
            String requestUri = handshakeComplete.requestUri();
            System.out.println("requestUri:"+requestUri);
            String subproTocol = handshakeComplete.selectedSubprotocol();
            System.out.println("subproTocol:"+subproTocol);
            handshakeComplete.requestHeaders().forEach(entry -> System.out.println("header key:"+entry.getKey()+ "\nvalue:"+  entry.getValue()));
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}
